package dongchel.vrp.localsearch;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import dongchel.vrp.entity.City;
import dongchel.vrp.entity.GlobalInformation;
import dongchel.vrp.entity.Route;
import dongchel.vrp.entity.Solution;
import dongchel.vrp.rachelinsertion.InsertionObject;

public class Mutation {
	
	
	//mutation combined with local search method
	public static Solution mutatedAndLocalSearch(Solution solution){
		Solution clonedSolution = (Solution) solution.clone();
		int operation = (int) Math.floor(Math.random()*5);
		
		if(operation == 0){
			LocalSearch.randTwoExchange(clonedSolution);
		}else if(operation == 1){
			LocalSearch.randCrossover(clonedSolution);
		}else if(operation == 2){
			LocalSearch.randExchange(clonedSolution);
		}else if(operation == 3){
			LocalSearch.randOrExchange(clonedSolution);
		}else{
			LocalSearch.randRelocation(clonedSolution);
		}
		return clonedSolution;
	}

	public static Solution swapMutate(Solution solution, int n) {
		Solution clonedSolution = (Solution) solution.clone();

		InsertionObject io = new InsertionObject();

		List<Move> moveList = new ArrayList<Move>();

		int i = 0;
		while (i < n) {
			Move move = Move.randomGeneMove(clonedSolution);
			boolean duplicate = false;
			for (int j = 0; j < moveList.size(); j++) {
				if (moveList.get(j).checkDuplicate(move)) {
					duplicate = true;
					break;
				}
			}
			if (!duplicate) {
				moveList.add(move);
				i++;
			}
		}

		for (i = 0; i < n; i++) {
			Move move = moveList.get(i);
			exeMove(clonedSolution,move);
		}

		clonedSolution.setId(GlobalInformation.getSolutionNum());
		return clonedSolution;
	}

	public static void exeMove(Solution solution, Move move) {

		if (move.getRouteIndexFrom() == move.getRouteIndexTo()) {
			Route route = solution.getRouteList().get(move.getRouteIndexFrom());
			Collections.swap(route.getCityList(), move.getCityIndexFrom(), move
					.getCityIndexTo());
			route.refreshGeneral();
		} else {
			Route route1 = solution.getRouteList()
					.get(move.getRouteIndexFrom());
			Route route2 = solution.getRouteList().get(move.getRouteIndexTo());

			City city1 = route1.getCityList().get(move.getCityIndexFrom());
			City city2 = route2.getCityList().get(move.getCityIndexTo());
			route1.getCityList().set(move.getCityIndexFrom(), city2);
			route2.getCityList().set(move.getCityIndexTo(), city1);
			route1.refreshGeneral();
			route2.refreshGeneral();
		}
	}

}
